import axios from 'axios';

import { type AccountStore } from '@/store';

export default class AccountService {
  constructor(private store: AccountStore) {}

  async update(): Promise<void> {
    if (!this.store.profilesLoaded) {
      await this.retrieveProfiles();
      this.store.setProfilesLoaded();
    }
    await this.loadAccount();
  }

  async retrieveProfiles(): Promise<boolean> {
    try {
      const res = await axios.get<any>('management/info');
      if (res.data?.activeProfiles) {
        this.store.setRibbonOnProfiles(res.data['display-ribbon-on-profiles']);
        this.store.setActiveProfiles(res.data.activeProfiles);
      }
      return true;
    } catch {
      return false;
    }
  }

  async retrieveAccount(): Promise<boolean> {
    try {
      const response = await axios.get<any>('api/account');
      if (response.status === 200 && response.data?.login) {
        const account = response.data;
        this.store.setAuthentication(account);
        return true;
      }
    } catch {
      // Ignore error
    }

    this.store.logout();
    return false;
  }

  async loadAccount() {
    if (this.store.logon) {
      return this.store.logon;
    }
<%_ if (authenticationTypeJwt) { _%>
    const token = localStorage.getItem('<%=jhiPrefixDashed %>-authenticationToken') ?? sessionStorage.getItem('<%=jhiPrefixDashed %>-authenticationToken');
    if (this.authenticated && this.userAuthorities && token) {
<%_ } else { _%>
    if (this.authenticated && this.userAuthorities) {
<%_ } _%>
      return;
    }

    const promise = this.retrieveAccount();
    this.store.authenticate(promise);
    promise.then(() => this.store.authenticate(null));
    await promise;
  }

  async hasAnyAuthorityAndCheckAuth(authorities: any): Promise<boolean> {
    if (typeof authorities === 'string') {
      authorities = [authorities];
    }

    return this.checkAuthorities(authorities);
  }

  get authenticated(): boolean {
    return this.store.authenticated;
  }

  get userAuthorities(): string[] {
    return this.store.account?.authorities;
  }

  private checkAuthorities(authorities: string[]): boolean {
    if (this.userAuthorities) {
      for (const authority of authorities) {
        if (this.userAuthorities.includes(authority)) {
          return true;
        }
      }
    }
    return false;
  }
}
